package exampleQuestions;

import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class InfixPrefixPostFixCalculator {

	/**
	 * Calculators
	 */
	public static void main(String[] args) {

		String expression = "45+9*3-2/4-10";

		double result = calculate(expression);
		
		System.out.println(result);

	}

	private static double calculate(String expression) {

		Stack<Operator> operators = new Stack<Operator>();
		Stack<Double> numbers = new Stack<Double>();
		
		Pattern pattern = Pattern.compile("(0|([1-9]\\d*)|\\*|/|\\+|-)");
		Matcher m = pattern.matcher(expression);
		
		Stack<String> elements = new Stack<String>();
		int index = 0;
		while(m.find(index)) {
			String s = expression.substring(m.start(), m.end());
			elements.push(s);
			index = m.end();
		}
			
			
		while (!elements.empty()) {
			
			String s = elements.pop();
			System.err.println(s);
			if(s.equals("+")) {
				while (!operators.empty() && operators.peek().compareTo(Operator.MINUS) > 0) {
					numbers.push(calculate(numbers.pop(), numbers.pop(), operators.pop()));
				}
				operators.add(Operator.PLUS);
			} else if(s.equals("-")) {
				while (!operators.empty() && operators.peek().compareTo(Operator.MINUS) > 0) {
					numbers.push(calculate(numbers.pop(), numbers.pop(), operators.pop()));
				}
				operators.add(Operator.MINUS);
			} else if(s.equals("*")) {
				operators.add(Operator.MULTIPLICATION);
			} else if(s.equals("/")) {
				operators.add(Operator.DIVISION);
			} else if(!s.equals("")){
				double arg = Double.parseDouble(s);
				numbers.add(arg);
			}
		}
		
		while (!operators.empty()) {
			numbers.push(calculate(numbers.pop(), numbers.pop(), operators.pop()));
		}

		return numbers.pop();
	}

	private static double calculate(Double a, Double b, Operator operator) {
		
		if(Operator.PLUS.equals(operator)) {
			return a + b;
		} else if(Operator.MINUS.equals(operator)) {
			return a - b;
		} else if(Operator.MULTIPLICATION.equals(operator)) {
			return a*b;
		} else {
			return a/b;
		}
	}

}

enum Operator {
	PLUS, MINUS, MULTIPLICATION, DIVISION
}
